package com.boost.tjvm.remote.migu;

import com.boost.tjvm.asm.MethodChangeClassAdapter;
import com.boost.tjvm.remote.ClassModifier;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;

/**
 * Created by cai.tian on 2017/4/24.
 */
public class SwapClassLoad extends ClassLoader {
    private ClassLoader parentr ;
    public SwapClassLoad(ClassLoader parentr ){
        super(parentr);
        this.parentr = parentr;
    }

/*    private String className="DsfAdapter";
    private String packageName="com.huawei.cgw.paymenthub.dsfadapter.adapter.";*/
    private String className="TestClass";
    private String packageName="com.boost.tjvm.remote.";

    private static final int INPUT_STREAM_DATA_CHUNK_SIZE = 4096;

    private Class getModf(String name) throws Exception {
        URL resource = getResource(name);
        ClassModifier classModifier = new ClassModifier(readStream(resource.openStream(),true));
        //byte[] modiByte = classModifier.modiftyUTF8Constant("com/huawei/openas/dsf/CommonInvoker", "xx/wheatInfo");

        byte[] modiByte = classModifier.modiftyUTF8Constant("org/apache/commons/lang3/StringUtils", "com/boost/tjvm/remote/TestClass");

        //saveFile(className+".class",modiByte);

        Method driveMtd = parentr.getClass().getMethod("defineClass",String.class,byte[].class,int.class,int.class);
        driveMtd.setAccessible(true);
        Object invoke = driveMtd.invoke(parentr, packageName+className, modiByte, 0, modiByte.length);

        return (Class)invoke;
    }


    protected Class<?> loadClass(String name, boolean resolve)
            throws ClassNotFoundException {
        if (!(packageName+className).equals(name)) {
            return super.loadClass(name, resolve);
        }
        synchronized (getClassLoadingLock(name)) {
            try {
                return getModf(packageName.replaceAll("\\.","/") + className +".class");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }


    private static byte[] readStream(final InputStream inputStream, final boolean close)
            throws IOException {
        if (inputStream == null) {
            throw new IOException("Class not found");
        }
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            byte[] data = new byte[INPUT_STREAM_DATA_CHUNK_SIZE];
            int bytesRead;
            while ((bytesRead = inputStream.read(data, 0, data.length)) != -1) {
                outputStream.write(data, 0, bytesRead);
            }
            outputStream.flush();
            return outputStream.toByteArray();
        } finally {
            if (close) {
                inputStream.close();
            }
        }
    }


    public static void saveFile(String filename,byte [] data)throws IOException{
        if(data != null){
            String filepath ="D:\\" + filename;
            File file  = new File(filepath);
            if(file.exists()){
                file.delete();
            }
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(data,0,data.length);
            fos.flush();
            fos.close();
        }
    }

}